/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package chameleon.model.formula.parser;

import chameleon.model.formula.Formula;
import chameleon.model.formula.Operator;
import java.io.IOException;
import java.util.Stack;

/**
 * This class represent the general structure for a parser. The lineRead_ element
 * is the parsing element. The token_ element is the current token. SackFormula_
 * is a stack that contains formulae, and stackOperator_ is a stack that contains
 * operators.
 *
 * The token_ elements contain a tag that describe the type of the elements, and
 * the string representation of the element.
 *
 * @author simon
 */
public abstract class AbstractParser {
    protected int pos_;
    protected String lineRead;
    protected Word token_;
    protected Stack stackFormula_;
    protected Stack stackOperator_;

    public AbstractParser(){
        pos_ = 0;
        stackFormula_ = new Stack();
        stackOperator_ = new Stack();
    }

    /**
     * This method push on the corresponding stack the token elemnt.
     *
     * If isOp == true we have an operator, otherwise we have a formula.
     *
     * @param isOp
     * @throws IOException
     */

    protected void push(boolean isOp) throws IOException{
        if (isOp)
            stackOperator_.push(new Operator(token_.toString()));
        else
            stackFormula_.push(new Formula(token_.toString()));
        token_ = nextToken();
    }

    /**
     * Exist-there a match between the token tag and the exepcted tag?
     * 
     * @param tag
     * @return
     */

    protected boolean match(int tag){
        if (token_.getTag() == tag)
            return true;
        else
            return false;
    }

    /**
     * Creates the formula corresponding to the operator on top of stackOperator_.
     */

    protected void createFormulaOnStack(){
        if (!stackOperator_.empty()){
            Formula right = (Formula) stackFormula_.pop();
            Operator op = (Operator) stackOperator_.pop();

            if (op.isUnary()){
                Formula formula = new Formula(right, op);
                stackFormula_.push(formula);
            }
            else{
                Formula left = (Formula) stackFormula_.pop();
                Formula formula = new Formula(left, right, op);
                stackFormula_.push(formula);
            }
        }
    }

    /**
     * Start of the parsing phase. Create the formula corresponding to lineRead_.
     * 
     * @return
     * @throws IOException
     */

    public Formula createFormula() throws IOException{
        token_ = nextToken();
        FORMULA();
        Formula formula = (Formula) stackFormula_.pop();
        if (stackFormula_.isEmpty() && stackOperator_.isEmpty())
            return formula;
        else
            throw new IOException("Parser :: error during the creation of the formula");
    }
    
    protected boolean isLessThanMax(int max) {
        boolean isTrue = true;

        for (int i = 0; i < max && isTrue; ++i){
            isTrue = (pos_+i < lineRead.length());
        }

        return isTrue;
    }

    protected abstract Word nextToken()throws IOException;
    protected abstract void FORMULA()throws IOException;
}
